package main

import (
	"encoding/binary"
	"io"
	"log"
	"net"
	"runtime"
	"time"
)

const maxBufLen = 10240
const defaultBufLen = 1024
const headLen = 6

func testmain() {
	log.Printf("game start\n")
	LenStackBuf := 1024
	addr := "0.0.0.0:3000"
	// port := 3000
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		log.Fatalf("lisent fail , err = %v\n", err)
	}
	var tempDelay time.Duration
	for {
		conn, err := ln.Accept()
		if err != nil {
			if ne, ok := err.(net.Error); ok && ne.Temporary() {
				if tempDelay == 0 {
					tempDelay = 5 * time.Millisecond
				} else {
					tempDelay *= 2
				}
				if max := 1 * time.Second; tempDelay > max {
					tempDelay = max
				}
				log.Printf("accept error: %v; retrying in %v\n", err, tempDelay)
				time.Sleep(tempDelay)
				continue
			}
			return
		}
		log.Printf("accept one connect\n")
		tempDelay = 0
		go func() {
			defer func() {
				conn.Close()
				if r := recover(); r != nil {
					if LenStackBuf > 0 {
						buf := make([]byte, LenStackBuf)
						l := runtime.Stack(buf, false)
						log.Printf("%v: %s\n", r, buf[:l])
					} else {
						log.Printf("%v\n", r)
					}
				}
			}()

			var msgLen uint32
			var msgID uint16
			var b [defaultBufLen]byte
			bufMsgHead := b[:headLen]
			bufMsgLen := b[:4]
			bufMsgID := b[4:6]
			for {
				if _, err := io.ReadFull(conn, bufMsgHead); err != nil {
					return
				}
				msgLen = binary.LittleEndian.Uint32(bufMsgLen)
				msgID = binary.LittleEndian.Uint16(bufMsgID)

				if msgLen > maxBufLen {
					log.Printf("read msg len = %v, id = %v\n", msgLen, msgID)
					return
				}

				if msgLen > 0 {
					var msgData []byte
					//				msgData := make([]byte, msgLen)
					if msgLen <= defaultBufLen {
						msgData = b[headLen : headLen+msgLen]
					} else {
						tBuf := make([]byte, headLen+msgLen)
						copy(tBuf, b[:headLen])
						msgData = tBuf[headLen : headLen+msgLen]
					}

					if _, err := io.ReadFull(conn, msgData); err != nil {
						return
					}
					log.Printf("read msg len = %v, id = %v, data = %v\n", msgLen, msgID, msgData)
					return
				}
			}
		}()
	}
}
